package com.refusea.train.config.filter

import jakarta.servlet.Filter
import jakarta.servlet.FilterChain
import jakarta.servlet.FilterConfig
import jakarta.servlet.ServletException
import jakarta.servlet.ServletRequest
import jakarta.servlet.ServletResponse
import jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.slf4j.MDC
import java.io.IOException
import java.time.LocalTime
import java.util.concurrent.atomic.AtomicInteger


/**
 * 打印 access 日志
 *
 * @author Zhang Yan 2024/3/23
 */
class AccessLogFilter : Filter {
    private val prefix: String

    init {
        val minute = LocalTime.now().minute
        prefix = if (minute < 10) "0$minute" else minute.toString()
    }

    override fun destroy() {
        // do nothing
    }

    @Throws(IOException::class, ServletException::class)
    override fun doFilter(servletRequest: ServletRequest, servletResponse: ServletResponse, filterChain: FilterChain) {
        val start = System.currentTimeMillis()
        MDC.put(KEY, prefix + sn.incrementAndGet())
        val uri = (servletRequest as HttpServletRequest).requestURI
        try {
            filterChain.doFilter(servletRequest, servletResponse)
        } finally {
            log.info(
                "{}, {}, {}",
                (servletResponse as HttpServletResponse).status,
                uri,
                System.currentTimeMillis() - start
            )
            MDC.remove(KEY)
        }
    }

    override fun init(filterConfig: FilterConfig) {
        // do nothing
    }

    companion object {
        private val log: Logger = LoggerFactory.getLogger("AccessLog")

        private const val KEY = "sn"
        private val sn = AtomicInteger()
    }
}
